use std::collections::HashMap;
use axum::body::{to_bytes, Body, Bytes};
use axum::extract::Request;
use axum::http::request::Parts;
use axum::middleware::Next;
use axum::response::{IntoResponse, Response};
use log::{error, info};
use serde_json::Value;
use crate::R;

/// 打印请求参数
/// 
/// 只打印`Content-Type`为`application/json`和`application/x-www-form-urlencoded`的请求
pub async fn print_request(req: Request, next: Next) -> Response {

    let is_json_content = is_json_content(&req);
    let is_form_content = is_form_content(&req);
    if is_json_content || is_form_content {
        let (parts, body) = req.into_parts();

        let bytes = to_bytes(body, usize::MAX)
            .await
            .unwrap_or_else(|_| Bytes::new());

        // 如果请求体为空，则不打印参数
        if bytes.is_empty() {
            return next_run(parts, bytes, next).await;
        }

        if let Ok(body) = std::str::from_utf8(&bytes) {

            if is_form_content {
                info!("请求参数: {}", body);
            } else {
                let json = serde_json::from_str(body);
                if let Err(e) = json {
                    error!("反序列化错误: {}", e);
                    return R::<()>::fail("请求参数错误").into_response();
                }
                let json: HashMap<String, Value> = json.unwrap();
                let result = serde_json::to_string(&json);
                match result {
                    Ok(res) => info!("请求参数: {}", res),
                    Err(e) => {
                        error!("序列化错误: {}", e);
                        return R::<()>::fail("请求参数错误").into_response();
                    }
                }
            }

        }
        return next_run(parts, bytes, next).await;
    }
    next.run(req).await
}


/// 打印响应结果
///
/// 只打印`Content-Type`为`application/json`的响应
pub async fn print_response(req: Request, next: Next) -> Response {

    let is_json_content = is_json_content(&req);

    let response = next.run(req).await;

    if !is_json_content {
        return response;
    }
    let (parts, body) = response.into_parts();

    let bytes = to_bytes(body, usize::MAX)
        .await
        .unwrap_or_else(|_| Bytes::new());

    // 如果请求体为空，则不打印响应结果
    if bytes.is_empty() {
        return Response::from_parts(parts, Body::from(bytes))
    }

    if let Ok(body) = std::str::from_utf8(&bytes) {
        info!("响应结果: {}", body);
    }
    Response::from_parts(parts, Body::from(bytes))
}

/// 检查是否JSON内容类型
fn is_json_content<B>(req: &Request<B>) -> bool {
    req.headers()
        .get("Content-Type")
        .map(|v| v.as_bytes().starts_with(b"application/json"))
        .unwrap_or(false)
}

/// 检查是否FORM内容类型
fn is_form_content<B>(req: &Request<B>) -> bool {
    req.headers()
        .get("Content-Type")
        .map(|v| {
            v.as_bytes()
                .starts_with(b"application/x-www-form-urlencoded")
        })
        .unwrap_or(false)
}

async fn next_run(parts: Parts, bytes: Bytes, next: Next) -> Response {
    // 重新构Request建供后续使用
    let req = Request::from_parts(parts, Body::from(bytes));
    next.run(req).await
}
